home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / intrvews / xgrab.lha / xgrab / ui / pparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-03-07  |  16.1 KB  |  1,015 lines

  1. /**
  2.    GRAB Graph Layout and Browser System
  3.  
  4.    Copyright (c) 1989, Tera Computer Company
  5.  **/
  6.  
  7.   /**
  8.      Parse predicates, building a parse tree in the process.
  9.      Uses recursive descent parsing, because it's so easy to write
  10.    **/
  11.  
  12. #include <stdio.h>
  13. #include "attribute.h"
  14. #include "digraph.h"
  15. #include "token.h"
  16. #include "pparse.h"
  17.  
  18. BOOL token_read;
  19. BOOL error;
  20. TOKEN current;
  21. int lineno;
  22.  
  23. extern char string_val[MAXBUFFER];
  24.  
  25. TOKEN get_token();
  26. TOKEN get_next_token();
  27. PTREE *get_ifstmt(), *get_setstmt(), *get_displaystmt(), *get_hidestmt();
  28. PTREE *get_focusstmt(), *get_coalescestmt(), *get_expandstmt();
  29. PTREE *get_breakstmt(), *get_continuestmt();
  30. PTREE *get_bexpr(), *get_bterm(), *get_bfactor();
  31. PTREE *get_node(), *get_nodel(), *get_attr(), *get_rval(), *get_rest_of_attr();
  32. PTREE *get_fnodel(), *get_rest_of_node(), *get_attr_name();
  33. PTREE *get_command(), *get_command_list(), *get_commands();
  34.  
  35. init_parse(pfile)
  36. FILE *pfile;
  37. {
  38.     init_reader(pfile);
  39.     lineno = 1;
  40.     error = FALSE;
  41.     token_read = FALSE;
  42. }
  43.  
  44. gobble_token()
  45. {
  46.     (void) get_token(TRUE, TRUE);
  47. }
  48.  
  49. TOKEN get_token(reserved, str_restricted)
  50. BOOL reserved, str_restricted;
  51.   /**
  52.      Get the next token.  Used along with lookahead (below) to implement
  53.      lookahead painlessly
  54.    **/
  55. {
  56.     if (token_read)
  57.     {
  58.     token_read = FALSE;
  59.     }
  60.     else
  61.     {
  62.     while((current = get_next_token(reserved, str_restricted)) == 
  63.           NEWLINE_TOKEN)
  64.       /* ignore newlines, except to keep track of the line number */
  65.     {
  66.         lineno++;
  67.     }
  68.     }
  69.  
  70.     return current;
  71. }
  72.  
  73. TOKEN lookahead(reserved, str_restricted)
  74. BOOL reserved, str_restricted;
  75.   /* return the next 'unread' token */
  76. {
  77.     if (!token_read)
  78.     {
  79.     token_read = TRUE;
  80.     while((current = get_next_token(reserved, str_restricted)) ==
  81.           NEWLINE_TOKEN)
  82.     {
  83.         lineno++;
  84.     }
  85.     }
  86.  
  87.     return current;
  88. }
  89.  
  90. BOOL match_token(t, reserved, str_restricted)
  91. TOKEN t;
  92. BOOL reserved, str_restricted;
  93.   /**
  94.      Check that the next token is t, if not, print an error message
  95.    **/
  96. {
  97.     TOKEN s;
  98.  
  99.     if ((s = get_token(reserved, str_restricted)) == t)
  100.     {
  101.     return TRUE;
  102.     }
  103.     else
  104.     {
  105.     print_lineno();
  106.     fprintf (stderr, "Expecting token ");
  107.     print_token(t, FALSE);    
  108.       /**
  109.          the preceding will look stupid if the token is STRING_TOKEN,
  110.          for example, because print_token will print the current
  111.          string_val.
  112.        **/
  113.     fprintf (stderr, " got ");
  114.     print_token(s, TRUE);
  115.     error = TRUE;
  116.     return FALSE;
  117.     }
  118. }
  119.     
  120. PTREE *get_command ()
  121.   /**
  122.      get a command 
  123.  
  124.      COMMAND -> HIDESTMT | IFSTMT | SETSTMT | COALESCESTMT | EXPANDSTMT |
  125.         DISPLAYSTMT | FOCUSSTMT | BREAKSTMT | CONTINUESTMT | 
  126.         ;
  127.    **/
  128. {
  129.     TOKEN t;
  130.  
  131.     ck;
  132.  
  133.     t = get_token(TRUE, TRUE);
  134.  
  135.     switch (t)
  136.     {
  137.     case EOF_TOKEN:
  138.         return NULL;
  139.     case SEMICOLON_TOKEN:
  140.         return NULL;
  141.     case IF_TOKEN:
  142.         return get_ifstmt();
  143.     case SET_TOKEN:
  144.         return get_setstmt();
  145.     case COALESCE_TOKEN:
  146.         return get_coalescestmt();
  147.     case EXPAND_TOKEN:
  148.         return get_expandstmt();
  149.     case HIDE_TOKEN:
  150.         return get_hidestmt();
  151.     case DISPLAY_TOKEN:
  152.         return get_displaystmt();
  153.     case FOCUS_TOKEN:
  154.         return get_focusstmt();
  155.     case BREAK_TOKEN:
  156.         return get_breakstmt();
  157.     case CONTINUE_TOKEN:
  158.         return get_continuestmt();
  159.     default:
  160.         print_lineno();
  161.         fprintf (stderr, "parse error: token ");
  162.         print_token(t, FALSE);
  163.         fprintf (stderr, " cannot begin a statement\n");
  164.         error = TRUE;
  165.         return NULL;
  166.     }
  167. }
  168.  
  169. PTREE *get_hidestmt()
  170.   /**
  171.      HIDESTMT -> hide NODE ;
  172.    **/
  173. {
  174.     PTREE *left, *this;
  175.     int tmp;
  176.  
  177.     ck;
  178.     tmp = lineno;
  179.  
  180.     left = get_node();
  181.     ck;
  182.  
  183.     ck_match(SEMICOLON_TOKEN);
  184.  
  185.     new(this, PTREE);
  186.     this->token = HIDE_TOKEN;
  187.     this->val = NULL;
  188.     this->lineno = tmp;
  189.     this->right = NULL;
  190.     this->left = left;
  191.  
  192.     return this;
  193. }
  194.  
  195. PTREE *get_displaystmt()
  196.   /**
  197.      DISPLAYSTMT -> display NODE ;
  198.    **/
  199. {
  200.     PTREE *left, *this;
  201.     int tmp;
  202.  
  203.     ck;
  204.  
  205.     tmp = lineno;
  206.     left = get_node();
  207.     ck;
  208.  
  209.     ck_match(SEMICOLON_TOKEN);
  210.  
  211.     new(this, PTREE);
  212.     this->token = DISPLAY_TOKEN;
  213.     this->val = NULL;
  214.     this->lineno = tmp;
  215.     this->right = NULL;
  216.     this->left = left;
  217.  
  218.     return this;
  219. }
  220.  
  221. PTREE *get_focusstmt()
  222.    /**
  223.       FOCUSSTMT -> focus NODE ;
  224.     **/
  225. {
  226.     PTREE *left, *this;
  227.     int tmp;
  228.  
  229.     ck;
  230.  
  231.     tmp = lineno;
  232.     left = get_node();
  233.     ck;
  234.  
  235.     ck_match(SEMICOLON_TOKEN);
  236.  
  237.     new(this, PTREE);
  238.     this->token = FOCUS_TOKEN;
  239.     this->val = NULL;
  240.     this->lineno = tmp;
  241.     this->right = NULL;
  242.     this->left = left;
  243.  
  244.     return this;
  245. }
  246.  
  247. PTREE *get_expandstmt()
  248.   /**
  249.      EXPANDSTMT -> expand NODE ;
  250.    **/
  251. {
  252.     PTREE *left, *this;
  253.     int tmp;
  254.  
  255.     ck;
  256.  
  257.     tmp = lineno;
  258.     left = get_node();
  259.     ck;
  260.  
  261.     ck_match(SEMICOLON_TOKEN);
  262.  
  263.     new(this, PTREE);
  264.     this->token = EXPAND_TOKEN;
  265.     this->val = NULL;
  266.     this->lineno = tmp;
  267.     this->right = NULL;
  268.     this->left = left;
  269.  
  270.     return this;
  271. }
  272.  
  273. PTREE *get_breakstmt()
  274.    /**
  275.       BREAKSTMT -> break ;
  276.     **/
  277. {
  278.     PTREE *this;
  279.     int tmp;
  280.  
  281.     ck;
  282.  
  283.     tmp = lineno;
  284.     ck_match(SEMICOLON_TOKEN);
  285.  
  286.     new(this, PTREE);
  287.     this->token = BREAK_TOKEN;
  288.     this->val = NULL;
  289.     this->lineno = tmp;
  290.     this->right = NULL;
  291.     this->left = NULL;
  292.  
  293.     return this;
  294. }
  295.  
  296. PTREE *get_continuestmt()
  297.   /**
  298.      CONTINUESTMT -> continue ;
  299.    **/
  300. {
  301.     PTREE *this;
  302.     int tmp;
  303.  
  304.     ck;
  305.  
  306.     tmp = lineno;
  307.     ck_match(SEMICOLON_TOKEN);
  308.  
  309.     new(this, PTREE);
  310.     this->token = CONTINUE_TOKEN;
  311.     this->val = NULL;
  312.     this->lineno = tmp;
  313.     this->right = NULL;
  314.     this->left = NULL;
  315.  
  316.     return this;
  317. }
  318.  
  319. PTREE *get_coalescestmt()
  320.   /**
  321.      COALESCESTMT -> coalesce NODE NODE ;
  322.    **/
  323. {
  324.     PTREE *left, *right, *this;
  325.     int tmp;
  326.  
  327.     ck;
  328.  
  329.     tmp = lineno;
  330.     left = get_node();
  331.     ck;
  332.  
  333.     right = get_node();
  334.     ck;
  335.  
  336.     ck_match(SEMICOLON_TOKEN);
  337.  
  338.     new(this, PTREE);
  339.     this->token = COALESCE_TOKEN;
  340.     this->val = NULL;
  341.     this->lineno = tmp;
  342.     this->right = right;
  343.     this->left = left;
  344.  
  345.     return this;
  346. }
  347.  
  348. PTREE *get_ifstmt()
  349.   /** 
  350.      'if' or 'elsif' has already been read 
  351.  
  352.      IFSTMT -> if BEXPR then COMMAND_LIST 
  353.            [elsif BEXPR then COMMAND_LIST ...]
  354.            [else COMMAND_LIST]
  355.            endif
  356.    **/
  357. {
  358.     PTREE *lleft, *rleft, *right, *this;
  359.     TOKEN t;
  360.     int tmp1, tmp2;
  361.  
  362.     ck;
  363.  
  364.     tmp1 = lineno;
  365.     lleft = get_bexpr();
  366.     ck;
  367.  
  368.     ck_match(THEN_TOKEN);
  369.  
  370.     tmp2 = lineno;
  371.     rleft = get_command_list();
  372.     ck;
  373.  
  374.     t = get_token(TRUE, TRUE);
  375.  
  376.     switch(t)
  377.     {
  378.     case ELSE_TOKEN:
  379.             right = get_command_list();
  380.         ck;
  381.  
  382.         ck_match(ENDIF_TOKEN);
  383.         break;
  384.     case ELSIF_TOKEN:
  385.             right = get_ifstmt();
  386.         ck;
  387.  
  388.         break;
  389.     case ENDIF_TOKEN:
  390.             right = NULL;
  391.         break;
  392.     default:
  393.         print_lineno();
  394.             fprintf(stderr, 
  395.                 "Invalid token in if statement after statement list:");
  396.         print_token(t, TRUE);
  397.             error = TRUE;
  398.             return NULL;
  399.     }
  400.  
  401.     new(this, PTREE);
  402.     this->token = IF_TOKEN;
  403.     this->val = NULL;
  404.     this->lineno = tmp1;
  405.     this->right = right;
  406.  
  407.     new(this->left, PTREE);
  408.     this->left->token = THEN_TOKEN;
  409.     this->left->val = NULL;
  410.     this->left->lineno = tmp2;
  411.     this->left->right = rleft;
  412.     this->left->left = lleft;
  413.     return this;
  414. }
  415.  
  416. PTREE *get_setstmt()
  417.   /**
  418.      SETSTMT -> set ATTR = RVAL ;
  419.    **/
  420. {
  421.     PTREE *left, *right, *this;
  422.     int tmp;
  423.  
  424.     ck;
  425.  
  426.     tmp = lineno;
  427.     left = get_attr();
  428.     ck;
  429.  
  430.     ck_match(EQUAL_TOKEN);
  431.  
  432.     right = get_rval();
  433.     ck;
  434.  
  435.     ck_match(SEMICOLON_TOKEN);
  436.  
  437.     new(this, PTREE);
  438.     this->token = SET_TOKEN;
  439.     this->val = NULL;
  440.     this->lineno = tmp;
  441.     this->left = left;
  442.     this->right = right;
  443.  
  444.     return this;
  445. }
  446.  
  447. PTREE *get_attr()
  448.    /**
  449.       ATTR -> fnodel . REST_OF_ATTR
  450.     **/
  451. {
  452.     PTREE *this, *left, *right;
  453.     int tmp;
  454.  
  455.     ck;
  456.  
  457.     tmp = lineno;
  458.     left = get_fnodel();
  459.     ck;
  460.  
  461.     ck_match(PERIOD_TOKEN);
  462.  
  463.     right = get_rest_of_attr();
  464.     ck;
  465.  
  466.     new(this, PTREE);
  467.     this->token = PERIOD_TOKEN;
  468.     this->val = NULL;
  469.     this->lineno = tmp;
  470.     this->left = left;
  471.     this->right = right;
  472.  
  473.     return this;
  474. }
  475.  
  476. PTREE *get_attr_name()
  477.   /**
  478.      ATTR_NAME -> STRING | brush | shape | color | displayed | coalescer |
  479.           node | edge
  480.    **/
  481. {
  482.     PTREE *this;
  483.     TOKEN t;
  484.  
  485.     ck;
  486.  
  487.     t = get_token(TRUE, TRUE);
  488.  
  489.     switch(t)
  490.     {
  491.     case STRING_TOKEN:
  492.         new(this, PTREE);
  493.         this->token = STRING_TOKEN;
  494.         strsave(this->val, string_val);
  495.         this->lineno = lineno;
  496.         this->left = NULL;
  497.         this->right = NULL;
  498.         break;
  499.     case BRUSH_TOKEN:
  500.     case SHAPE_TOKEN:
  501.     case COLOR_TOKEN:
  502.     case DISPLAYED_TOKEN:
  503.     case COALESCER_TOKEN:
  504.     case NODE_TOKEN:
  505.     case EDGE_TOKEN:
  506.             new(this, PTREE);
  507.         this->token = t;
  508.         this->val = NULL;
  509.         this->lineno = lineno;
  510.         this->right = NULL;
  511.         this->left = NULL;
  512.         break;
  513.     default:
  514.         print_lineno();
  515.         fprintf(stderr, "Attribute name cannot be ");
  516.         print_token(t, TRUE);
  517.         error = TRUE;
  518.         return NULL;
  519.     }
  520.  
  521.     return this;
  522. }
  523.  
  524. PTREE *get_rest_of_attr()
  525.   /**
  526.      REST_OF_ATTR -> ATTR_NAME | NODEL . REST_OF_ATTR
  527.    **/
  528. {
  529.     PTREE *this, *left, *right;
  530.     TOKEN t;
  531.     int tmp;
  532.  
  533.     ck;
  534.  
  535.     t = lookahead(TRUE, TRUE);
  536.  
  537.     if (t == STRING_TOKEN)
  538.     {
  539.     left = get_nodel();
  540.     ck;
  541.  
  542.     if (lookahead(TRUE, TRUE) == PERIOD_TOKEN)
  543.     {
  544.         gobble_token();
  545.         tmp = lineno;
  546.  
  547.         right = get_rest_of_attr();
  548.         ck;
  549.  
  550.         new(this, PTREE);
  551.         this->token = PERIOD_TOKEN;
  552.         this->val = NULL;
  553.         this->lineno = tmp;
  554.         this->left = left;
  555.         this->right = right;
  556.     }
  557.     else
  558.     {
  559.         this = left;
  560.     }
  561.     }
  562.     else if (attr_starter(t))
  563.     {
  564.     this = get_attr_name();
  565.     ck;
  566.     }
  567.     else if (node_starter(t))
  568.     {
  569.     left = get_nodel();
  570.     ck;
  571.  
  572.     ck_match(PERIOD_TOKEN);
  573.      
  574.     tmp = lineno;
  575.     right = get_rest_of_attr();
  576.     ck;
  577.  
  578.     new(this, PTREE);
  579.     this->token = PERIOD_TOKEN;
  580.     this->val = NULL;
  581.     this->lineno = tmp;
  582.     this->left = left;
  583.     this->right = right;
  584.     }
  585.     else
  586.     {
  587.     print_lineno();
  588.     fprintf(stderr, "Attribute designator cannot start with ");
  589.     gobble_token();
  590.     print_token(t, TRUE);
  591.     error = TRUE;
  592.     return NULL;
  593.     }
  594.  
  595.     return this;
  596. }
  597.  
  598. PTREE *get_node()
  599.   /**
  600.      NODE -> FNODEL . [REST_OF_NODE]
  601.    **/
  602. {
  603.     PTREE *this, *left, *right;
  604.     TOKEN t;
  605.     int tmp;
  606.  
  607.     ck;
  608.  
  609.     left = get_fnodel();
  610.     ck;
  611.  
  612.     ck_match(PERIOD_TOKEN);
  613.  
  614.     tmp = lineno;
  615.     t = lookahead(TRUE, TRUE);
  616.  
  617.     if (node_starter(t))
  618.     {
  619.         right = get_rest_of_node();
  620.         ck;
  621.     }
  622.     else
  623.     {
  624.         right = NULL;
  625.     }
  626.  
  627.     new(this, PTREE);
  628.     this->token = PERIOD_TOKEN;
  629.     this->val = NULL;
  630.     this->lineno = tmp;
  631.     this->right = right;
  632.     this->left = left;
  633.     return this;
  634. }
  635.  
  636. PTREE *get_rest_of_node()
  637.    /**
  638.       REST_OF_NODE -> NODEL . [REST_OF_NODE]
  639.     **/
  640. {
  641.     PTREE *this, *left, *right;
  642.     TOKEN t;
  643.     int tmp;
  644.  
  645.     ck;
  646.  
  647.     left = get_nodel();
  648.     ck;
  649.  
  650.     ck_match(PERIOD_TOKEN);
  651.  
  652.     tmp = lineno;
  653.     t = lookahead(TRUE, TRUE);
  654.  
  655.     if (node_starter(t))
  656.     {
  657.         right = get_rest_of_node();
  658.         ck;
  659.     }
  660.     else
  661.     {
  662.         right = NULL;
  663.     }
  664.  
  665.     new(this, PTREE);
  666.     this->token = PERIOD_TOKEN;
  667.     this->val = NULL;
  668.     this->lineno = tmp;
  669.     this->right = right;
  670.     this->left = left;
  671.     return this;
  672. }
  673.  
  674. PTREE *get_fnodel()
  675.   /** 
  676.      first field of a node/edge designator 
  677.  
  678.      FNODEL -> QSTRING | e        e = empty string 
  679.    **/
  680. {
  681.     PTREE *this;
  682.     TOKEN t;
  683.  
  684.     ck;
  685.  
  686.     t = lookahead(TRUE, TRUE);
  687.  
  688.     switch(t)
  689.     {
  690.     case PERIOD_TOKEN:
  691.         this = NULL;
  692.         break;
  693.     case QSTRING_TOKEN:
  694.         gobble_token();
  695.  
  696.         new(this, PTREE);
  697.         this->token = t;
  698.         strsave(this->val, string_val);
  699.         this->lineno = lineno;
  700.         this->right = NULL;
  701.         this->left = NULL;
  702.         break;
  703.     default:
  704.         gobble_token();
  705.         print_lineno();
  706.         fprintf(stderr, "Node/edge designator cannot start with ");
  707.         print_token(t, TRUE);
  708.         error = TRUE;
  709.         return NULL;
  710.     }
  711.  
  712.     return this;
  713. }
  714.         
  715. PTREE *get_nodel()
  716.   /**
  717.      NODEL -> STRING | in | out | source | sink | parents | children |
  718.           ancestors | descendants
  719.    **/
  720. {
  721.     PTREE *this;
  722.     TOKEN t;
  723.  
  724.     ck;
  725.  
  726.     t = get_token(TRUE, TRUE);
  727.  
  728.     switch(t)
  729.     {
  730.     case STRING_TOKEN:
  731.         new(this, PTREE);
  732.         this->token = t;
  733.         strsave(this->val, string_val);
  734.         this->lineno = lineno;
  735.         this->right = NULL;
  736.         this->left = NULL;
  737.         break;
  738.     case IN_TOKEN:
  739.     case OUT_TOKEN:
  740.     case SOURCE_TOKEN:
  741.     case SINK_TOKEN:
  742.     case PARENTS_TOKEN:
  743.     case CHILDREN_TOKEN:
  744.     case ANCESTORS_TOKEN:
  745.     case DESCENDANTS_TOKEN:
  746.         new(this, PTREE);
  747.         this->token = t;
  748.         this->val = NULL;
  749.         this->lineno = lineno;
  750.         this->right = NULL;
  751.         this->left = NULL;
  752.         break;
  753.     default:
  754.         print_lineno();
  755.         fprintf(stderr, "Node/edge designator cannot start with ");
  756.         print_token(t, TRUE);
  757.         error = TRUE;
  758.         return NULL;
  759.     }
  760.  
  761.     return this;
  762. }
  763.  
  764. PTREE *get_rval()
  765.   /**
  766.      RVAL = ATTR | QSTRING
  767.    **/
  768. {
  769.     int tmp;
  770.  
  771.     ck;
  772.  
  773.     if (lookahead(TRUE, TRUE) == QSTRING_TOKEN)
  774.     {
  775.         PTREE *left;
  776.  
  777.     gobble_token();
  778.     new(left, PTREE);
  779.     left->token = QSTRING_TOKEN;
  780.     strsave(left->val, string_val);
  781.     left->lineno = lineno;
  782.     left->right = left->left = NULL;
  783.  
  784.     if (lookahead(TRUE, TRUE) == PERIOD_TOKEN)
  785.     {
  786.         PTREE *right, *this;
  787.  
  788.         gobble_token();
  789.         tmp = lineno;
  790.         right = get_rest_of_attr();
  791.         ck;
  792.  
  793.         new(this, PTREE);
  794.         this->token = PERIOD_TOKEN;
  795.         this->val = NULL;
  796.         this->lineno = tmp;
  797.         this->left = left;
  798.         this->right = right;
  799.         return this;
  800.     }
  801.     else
  802.     {
  803.         return left;
  804.     }
  805.     }
  806.     else
  807.     {
  808.     return get_attr();
  809.     }
  810. }
  811.  
  812.   /**
  813.      The following 3 functions implement precedence and associativity
  814.      rules for boolean expressions
  815.    **/
  816.  
  817. PTREE *get_bexpr()
  818.   /**
  819.      BEXPR -> BTERM | BTERM and BEXPR | BTERM or BEXPR
  820.    **/
  821. {
  822.     PTREE *this, *left;
  823.     TOKEN t;
  824.     int tmp;
  825.  
  826.     ck;
  827.  
  828.     left = get_bterm();
  829.     ck;
  830.  
  831.     if ((t = lookahead(TRUE, TRUE)) == AND_TOKEN || t == OR_TOKEN)
  832.     {
  833.     PTREE *right;
  834.  
  835.     gobble_token();
  836.     tmp = lineno;
  837.     right = get_bexpr();
  838.     ck;
  839.  
  840.     new(this, PTREE);
  841.     this->token = t;
  842.     this->val = NULL;
  843.     this->lineno = tmp;
  844.     this->right = right;
  845.     this->left = left;
  846.     return this;
  847.     }
  848.     else
  849.     {
  850.     return left;
  851.     }
  852. }
  853.  
  854. PTREE *get_bterm()
  855.   /**
  856.      BTERM -> not BFACTOR | BFACTOR
  857.    **/
  858. {
  859.     PTREE *this, *left;
  860.     int tmp;
  861.  
  862.     ck;
  863.  
  864.     if (lookahead(TRUE, TRUE) == NOT_TOKEN)
  865.     {
  866.     gobble_token();
  867.     tmp = lineno;
  868.     left = get_bfactor();
  869.     ck;
  870.  
  871.     new(this, PTREE);
  872.     this->token = NOT_TOKEN;
  873.     this->val = NULL;
  874.     this->lineno = tmp;
  875.     this->right = NULL;
  876.     this->left = left;
  877.     return this;
  878.     }
  879.     else
  880.     {
  881.     return get_bfactor();
  882.     }
  883. }
  884.  
  885. PTREE *get_bfactor()
  886.   /**
  887.      BFACTOR -> ( BEXPR ) | RVAL | RVAL = RVAL
  888.    **/
  889. {
  890.     PTREE *this, *left, *right;
  891.     int tmp;
  892.  
  893.     ck;
  894.  
  895.     if (lookahead(TRUE, TRUE) == OPENPAREN_TOKEN)
  896.     {
  897.     gobble_token();
  898.     this = get_bexpr();
  899.     ck;
  900.  
  901.     ck_match(CLOSEPAREN_TOKEN);
  902.     }
  903.     else
  904.     {
  905.     left = get_rval();
  906.     ck;
  907.  
  908.     if (lookahead(TRUE, TRUE) == EQUAL_TOKEN)
  909.     {
  910.         gobble_token();
  911.         tmp = lineno;
  912.         right = get_rval();
  913.         ck;
  914.     }
  915.     else
  916.     {
  917.         tmp = lineno;
  918.         right = NULL;
  919.     }
  920.  
  921.     new(this, PTREE);
  922.     this->token = EQUAL_TOKEN;
  923.     this->val = NULL;
  924.     this->lineno = tmp;
  925.     this->right = right;
  926.     this->left = left;
  927.     }
  928.  
  929.     return this;
  930. }
  931.  
  932. PTREE *get_command_list()
  933.   /**
  934.      COMMAND_LIST -> COMMAND [COMMAND_LIST]
  935.    **/
  936. {
  937.     PTREE *this, *left, *right;
  938.     TOKEN t;
  939.     int tmp;
  940.  
  941.     ck;
  942.  
  943.     t = lookahead(TRUE, TRUE);
  944.  
  945.     if (!command_list_ender(t))
  946.     {
  947.     tmp = lineno;
  948.     left = get_command();
  949.     ck;
  950.  
  951.     right = get_command_list();
  952.     ck;
  953.  
  954.     new(this, PTREE);
  955.     this->token = SEMICOLON_TOKEN;
  956.     this->val = NULL;
  957.     this->lineno = tmp;
  958.     this->right = right;
  959.     this->left = left;
  960.  
  961.     return this;
  962.     }
  963.     else
  964.     {
  965.     return NULL;
  966.     }
  967. }
  968.  
  969. PTREE *get_commands(err)
  970. BOOL *err;
  971.   /**
  972.      Get the commands (function to call from the top level)
  973.    **/
  974. {
  975.     PTREE *this;
  976.     TOKEN t;
  977.  
  978.     this = get_command_list();
  979.  
  980.     if (error)
  981.     {
  982.     gobble_rest_of_tokens();
  983.     *err = TRUE;
  984.     return NULL;
  985.     }
  986.     else if ((t = lookahead(TRUE, TRUE)) != EOF_TOKEN)
  987.       /* check the file didn't end prematurely */
  988.     {
  989.     print_lineno();
  990.     fprintf(stderr, "Cannot end commands with ");
  991.     print_token(t, TRUE);
  992.     gobble_token();
  993.     gobble_rest_of_tokens();
  994.     *err = TRUE;
  995.     return NULL;
  996.     }
  997.     else
  998.     {
  999.     err = FALSE;
  1000.     return this;
  1001.     }
  1002. }
  1003.  
  1004. gobble_rest_of_tokens()
  1005. {
  1006.     while (get_token(TRUE, TRUE) != EOF_TOKEN)
  1007.     {
  1008.     }
  1009. }
  1010.  
  1011. print_lineno()
  1012. {
  1013.     fprintf(stderr, "on line #%d:  ", lineno);
  1014. }
  1015.